package j2024.j202409;

import java.util.Arrays;

public class j0916 {
    /**
     * 189. 轮转数组
     * 给定一个整数数组 nums，将数组中的元素向右轮转 k 个位置，其中 k 是非负数。
     * @param nums
     * @param k
     */
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] ret = new int[n];
        for (int i = 0; i < n; i++) {
            ret[(i+k)%n] = nums[i];
        }
        System.arraycopy(ret,0,nums,0,n);
    }

    /**
     * 121. 买卖股票的最佳时机
     * 给定一个数组 prices ，它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
     *
     * 你只能选择 某一天 买入这只股票，并选择在 未来的某一个不同的日子 卖出该股票。
     * 设计一个算法来计算你所能获取的最大利润。
     *
     * 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润，返回 0 。
     * @param prices
     * @return
     */
    public int maxProfit(int[] prices) {
        int minVal = Integer.MAX_VALUE;
        int ret = 0;
        for (int i = 0; i < prices.length; i++) {
            minVal = Math.min(minVal,prices[i]);
            ret = Math.max(prices[i]-minVal,ret);
        }
        return ret;
    }

    /**
     * 122. 买卖股票的最佳时机 II
     * 给你一个整数数组 prices ，其中 prices[i] 表示某支股票第 i 天的价格。
     *
     * 在每一天，你可以决定是否购买和/或出售股票。
     * 你在任何时候 最多 只能持有 一股 股票。
     * 你也可以先购买，然后在 同一天 出售。
     *
     * 返回 你能获得的 最大 利润 。
     * @param prices
     * @return
     */
    public int maxProfit1(int[] prices) {
        int ret = 0;
        for (int i = 0; i < prices.length; i++) {
            if(i+1 < prices.length && prices[i]<prices[i+1]){
                ret+=prices[i+1]-prices[i];
            }
        }
        return ret;
    }

    /**
     * 55. 跳跃游戏
     * 给你一个非负整数数组 nums ，你最初位于数组的 第一个下标 。
     * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
     *
     * 判断你是否能够到达最后一个下标，如果可以，返回 true ；否则，返回 false 。
     * @param nums
     * @return
     */
    public static boolean canJump(int[] nums) {
        int n = nums.length;
        int left = 0,right = 0,maxI = 0;
        while(left<=right){
            if(right>=n-1){
                return true;
            }
            for (int i = left; i <= right; i++) {
                maxI = Math.max(i+nums[i],maxI);
            }
            left = right+1;
            right = maxI;
        }
        return false;
    }

    public static void main(String[] args) {
        int[] nums = {2,3,1,1,4};
        canJump(nums);
    }

    /**
     * 45. 跳跃游戏 II
     * 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。
     *
     * 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。
     * 换句话说，如果你在 nums[i] 处，你可以跳转到任意 nums[i + j] 处:
     *
     * 0 <= j <= nums[i]
     * i + j < n
     * 返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。
     * @param nums
     * @return
     */
    public int jump(int[] nums) {
        int n = nums.length;
        int left = 0,right = 0,ret = 0,maxI = 0;
        while(left<=right){
            if(right>=n-1){
                return ret;
            }
            for (int i = left; i <= right; i++) {
                maxI = Math.max(maxI,i+nums[i]);
            }
            left = right+1;
            right = maxI;
            ret++;
        }
        return -1;
    }
    public int jump2(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        Arrays.fill(dp,Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if(nums[j]+j>=i){
                    dp[i] = Math.min(dp[i],dp[j]+1);
                }
            }
        }
        return dp[n-1];
    }
}
